Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit 216185c40e6c01b069cec43c7618f20c8deef7b6


Parents : 499caf4
Author : Sudo-Ivan <ivan@quad4.io>
Signature : Signature validation error
Date : 2026-03-06T02:19:17-06:00

Add overlay style stripping functionality in MicronParser and enhance event handling in NomadNetworkPage

Changes
Diff

diff --git a/meshchatx/src/frontend/components/nomadnetwork/NomadNetworkPage.vue b/meshchatx/src/frontend/components/nomadnetwork/NomadNetworkPage.vue
index 45a0ab26..6e472101 100644
--- a/meshchatx/src/frontend/components/nomadnetwork/NomadNetworkPage.vue
+++ b/meshchatx/src/frontend/components/nomadnetwork/NomadNetworkPage.vue
@@ -537,17 +537,17 @@ export default {
);
},
onElementClick(event) {
- // find the closest ancestor (or the clicked element itself) with data-action="openNode"
const element = event.target.closest('[data-action="openNode"]');
if (!element) {
return;
}
- // get the destination and fields
+ event.preventDefault();
+ event.stopPropagation();
+
const destination = element.getAttribute("data-destination");
const fields = element.getAttribute("data-fields");
- // navigate to destination
this.onNodePageUrlClick(destination, fields);
},
async onWebsocketMessage(message) {
@@ -1615,4 +1615,21 @@ pre.text-wrap > div > :last-child {
pre a:hover {
text-decoration: underline;
}
+
+.nodeContainer input[type="text"],
+.nodeContainer input[type="password"] {
+ font-family:
+ Roboto Mono Nerd Font,
+ monospace;
+ font-size: 1em;
+ line-height: 1;
+ padding: 0;
+ margin: 0;
+ border: 0;
+ border-bottom: 1px solid currentColor;
+ border-radius: 0;
+ background: transparent;
+ color: inherit;
+ box-sizing: content-box;
+}
</style>

diff --git a/meshchatx/src/frontend/js/MicronParser.js b/meshchatx/src/frontend/js/MicronParser.js
index b8b3cf8c..39664efa 100644
--- a/meshchatx/src/frontend/js/MicronParser.js
+++ b/meshchatx/src/frontend/js/MicronParser.js
@@ -79,6 +79,35 @@ class MicronParser {
return `nomadnetwork://${url}`;
}
+ /**
+ * Remove CSS properties that can create full-screen overlays and block the app UI.
+ * Nomad Network page content (e.g. dynamic server pages) may contain such styles.
+ */
+ static stripOverlayStyles(html) {
+ if (typeof html !== "string") return html;
+ const dangerousProps = ["zindex", "inset", "top", "left", "right", "bottom", "transform"];
+ return html.replace(/(\s)style="([^"]*)"/g, (match, space, styleValue) => {
+ const declarations = styleValue.split(";").filter(Boolean);
+ const safe = declarations.filter((decl) => {
+ const colon = decl.indexOf(":");
+ if (colon <= 0) return false;
+ const rawProp = decl.slice(0, colon).trim();
+ const prop = rawProp.toLowerCase().replace(/-/g, "");
+ const val = decl
+ .slice(colon + 1)
+ .trim()
+ .toLowerCase();
+ if (prop === "position" && (val === "fixed" || val === "sticky")) return false;
+ if (dangerousProps.includes(prop)) return false;
+ if (prop === "width" && /100v[wh]/.test(val)) return false;
+ if (prop === "height" && /100v[hw]/.test(val)) return false;
+ return true;
+ });
+ const out = safe.join("; ").trim();
+ return out ? `${space}style="${out}"` : "";
+ });
+ }
+
parseHeaderTags(markup) {
let pageFg = null;
let pageBg = null;
@@ -177,11 +206,12 @@ class MicronParser {
}
try {
- return DOMPurify.sanitize(html, {
+ const sanitized = DOMPurify.sanitize(html, {
USE_PROFILES: { html: true },
ALLOWED_URI_REGEXP:
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp|nomadnetwork|lxmf):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i,
});
+ return MicronParser.stripOverlayStyles(sanitized);
} catch (error) {
console.warn(
"DOMPurify is not installed. Include it above micron-parser.js or run npm install dompurify ",


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────